<template>
    <div class=" waterfall" ref="waterfall">
        <div class="grid gap-4" :style="`grid-template-columns: repeat(${col}, minmax(0,1fr));`">
            <div class="waterfall-items grow" v-for="(col, colIndex) in columns">
                <div class="waterfall-item" v-for="(item, itemIndex) in col.items">
                    <slot :data="item.data" :itemIndex="itemIndex" :colIndex="colIndex" :size="item.size" name="item">
                    </slot>
                </div>
            </div>
        </div>
    </div>
</template>
    
<script setup lang='ts'>

const props = withDefaults(defineProps<{
    items: WaterfallItems;
    mode?: 'image' | 'custom';
    imageField?: 'url' | 'src';
    col?: number;
}>(), {
    mode: 'custom',
    imageField: 'url',
    col: 2
})
const columns = ref(Array.from({ length: props.col }).map<{
    items: WaterfallItems,
    height: number,
    index: number
}>((item, index) => {
    return {
        items: [],
        height: 0,
        index
    }
}))
var itemNumber = 0;
const calculatePosition = (item: WaterfallItem) => {
    const height = item.size.height / item.size.width * 100;
    const low = columns.value.sort((a, b) => a.height - b.height)[0];
    low.height += height;
    low.items.push(item)
}

const customSize = (items: WaterfallItems) => {
    items.forEach(calculatePosition)
    return true;
}

const imageGenSize = (items: WaterfallItems) => {
    const promiseItems = toRaw(items)
        .map(item => new Promise<WaterfallItem>((resolve, reject) => {
            const img = new Image()
            img.src = item.data[props.imageField];
            img.onload = () => {
                item.size.width = img.width
                item.size.height = img.height
                resolve(item)
            }
            img.onerror = (e) => {
                reject(e);
            }
        }));
    Promise.allSettled(promiseItems).then((res) => {
        //@ts-ignore
        res.filter(({ status }) => status == "fulfilled").map(item => item.value).forEach(calculatePosition)
    })
    return true;
}

const handlers = [
    {
        type: 'custom',
        handler: customSize
    },
    {
        type: 'image',
        handler: imageGenSize
    }
]

watch(() => props.items, () => {
    const items = props.items.slice(itemNumber, props.items.length)
    itemNumber = props.items.length
    handlers.find(item => item.type == props.mode)?.handler(items) || customSize(items);
}, {
    immediate: true,
    deep: true
})
// watch(()=>props.col,()=>{
//     console.log(props.col)
//     handlers.find(item => item.type == props.mode)?.handler(props.items) || customSize(props.items);
// })
</script>
    
<style></style>